home *** CD-ROM | disk | FTP | other *** search
- ;
- ;
- CSEG segment para public 'CODE'
- assume cs:cseg,ds:cseg,ss:cseg,es:cseg
- org 100h ; .COM file format
- BEGIN: jmp PR_MAIN ; Skip around data declarations
- COPYRIGHT db 'PRint (C) 1985, Dickinson Associates Inc.'
- db 13,10,'$'
- VALID_IN db '/abcdefghijklmnopqrstuvwxyz,;=',9
- VALID_OUT db '\ABCDEFGHIJKLMNOPQRSTUVWXYZ',4 dup(32)
- VALID_NUM equ $ - VALID_OUT + 1
- FN_AREA db 77 dup (0)
- FN_LOC dw offset FN_AREA ; Initialize at FN_AREA
- PRN equ 4 ; PC-DOS printer device handle
- MAX_LINES equ 55
- MAX_CHARS equ 80
- FILE_HANDLE dw 0
- READ_LENGTH equ 256
- READ_BUFFER db READ_LENGTH dup (0),0
- READ_PTR dw offset READ_BUFFER
- PRINT_LENGTH equ 256
- PRINT_BUFFER db PRINT_LENGTH dup (0)
- PRINT_PTR dw offset PRINT_BUFFER
- EOF_FOUND db 0
- CHAR_COUNT dw 0
- LINE_COUNT db 0
- PAGE_COUNT db 0
- BIN_ASC db 10
- HEAD_1 db 13,10,13,10,'*',78 dup ('-'),'*',13,10
- HEAD_2A db '| File: '
- HEAD_2B db 70 dup (' '),'|',13,10
- HEAD_3A db '| Saved: '
- HEAD_3B db '00-00-00 at '
- HEAD_3C db '00:00:00 '
- HEAD_3D db '0m',39 dup (' '),'Page '
- HEAD_3E db '00 |',13,10
- HEAD_4 db '*',78 dup ('-'),'*',13,10,13,10
- HEAD_LGTH dw $ - HEAD_1
- ERR_HEAD db 10,13,'PRint Error - $'
- NO_FILE db 'Correct Syntax is:',13,10,10
- db 'PR [d:][path]filename[.ext]$'
- FILE_NOT_FOUND db 'File Not Found$'
- OPEN_FAILURE db 'File Open Failure$'
- READ_FAILURE db 'File Read Failure$'
- ERR_TAIL db 10,10,13,' . . . Aborting',10,13,13,'$'
- ;
- PR_MAIN proc near ; PR's main program
- lea dx,COPYRIGHT ; Display copyright notice
- mov ah,9h ; Request display string
- int 21h ; Call PC-DOS
- mov si,80h ; Point SI to beginning of PSP parm area
- lea di,FN_AREA ; Point SI to internal file name area
- mov cl,byte ptr [si] ; Get byte count to AL
- xor ch,ch ; Zero CH
- jcxz NONE ; If CX is zero, no parameters passed
- cld ; Set direction flag to forward
- inc si ; Adjust SI to beginning of parms
- mov dx,0 ; Use DX for leading blanks flag
- CLEAN: lodsb ; Load each character to AL
- push di ; Save DI on stack
- mov di,offset VALID_IN ; Point to table of valid inputs
- push cx ; Save CX on stack
- mov cx,VALID_NUM ; Set CX to number of inputs to look for
- repne scasb ; See if any are in AL
- jcxz CLEAND ; If not, change nothing
- mov bx,VALID_NUM ; Set up BX to point to valid output
- sub bx,cx ; This will leave BX one off
- mov al,VALID_OUT [bx - 1] ; Load the valid output (adj BX) to AL
- CLEAND: pop cx ; Restore CX
- pop di ; Restore DI
- cmp dx,1 ; If leading blanks have been stripped,
- je CLEANC ; go check for colons & other things
- cmp al,' ' ; Is AL a leading blank?
- je CLEANX ; Yes, ignore it & don't store it
- CLEANC: mov dx,1 ; If here, leading blanks are stripped
- cmp al,':' ; Is AL a colon?
- je DELIM ; Yes, it's a potential FN delimiter
- cmp al,'\' ; Is AL a backslash?
- jne DELIMX ; Yes, it's a potential FN delimiter
- DELIM: mov FN_LOC,di ; Set FN_LOC at current DI + 1
- inc FN_LOC ; -- last one set will be correct
- DELIMX: stosb ; Store modified AL back to PSP
- CLEANX: loop CLEAN ; Loop until CX is zero
- jmp FINDF ; Go see if file exists
- NONE: lea dx,NO_FILE ; Exit with error if no parameter
- jmp EREXIT ; passed
- FINDF: mov ah,4eh ; Request find 1st file
- mov cx,0 ; Set CX for normal files
- lea dx,FN_AREA ; Point DX to internal file name area
- int 21h ; Call PC-DOS
- jnc FOUNDF ; Ok, found the 1st file
- lea dx,FILE_NOT_FOUND ; If 1st file not found, exit
- jmp EREXIT ; with error
- FOUNDF: mov EOF_FOUND,0 ; Initialize end of file flag
- mov PAGE_COUNT,0 ; Initialize page counter
- mov FILE_HANDLE,0 ; Initialize file handle
- mov di,FN_LOC ; DI points to end of path
- mov si,9eh ; SI points to file name in default DTA
- mov cx,13 ; DTA file name has 13 bytes
- rep movsb ; Move bytes to FN_LOC (in FN_AREA)
- mov ah,3dh ; Request open file pointed to by DX
- mov al,0 ; Read permission requested
- lea dx,FN_AREA ; Internal File Name Area
- int 21h ; Call PC-DOS
- mov FILE_HANDLE,ax ; Save File Handle contained in AX
- jnc DO_PR ; No carry means successfully opened
- lea dx,OPEN_FAILURE ; Open file failed, exit
- jmp EREXIT ; with error message
- DO_PR: call STAMP ; Set file name, date & time stamps
- call PAGE_HEAD ; Print page header
- mov di,PRINT_PTR ; Initialize DI to PRINT_BUFFER
- PRLOOP: call READ_FILE ; Read data to buffer
- jc EREXIT ; Exit if error
- jcxz FINISH ; If CX is zero, end of file was reached
- call PRINT ; Format and print buffered data
- cmp EOF_FOUND,0 ; Was end of file flag set?
- je PRLOOP ; No, keep going
- FINISH: call NEW_PAGE ; Yes, print page feed
- call CLOSE_FILE ; Close file
- mov ah,4fh ; Request find next file
- mov cx,0 ; Set CX for normal files
- int 21h ; Call PC-DOS
- jnc FOUNDF ; If no carry then found the next file
- EXIT: ret ; If carry, exit to PC-DOS
- EREXIT: push dx ; Save error message pointer on stack
- mov dx,offset ERR_HEAD ; Display error header
- mov ah,9 ; Request display string
- int 21h ; Call PC-DOS
- pop dx ; Restore error message pointer
- mov ah,9 ; Request display string
- int 21h ; Call PC-DOS
- mov dx,offset ERR_TAIL ; Display error tail
- mov ah,9 ; Request display string
- int 21h ; Call PC-DOS
- call CLOSE_FILE ; Close any open file
- jmp EXIT ; Go exit to PC-DOS (all errors fatal)
- PR_MAIN endp
- ;
- READ_FILE proc near ; Load CX bytes to read buffer
- mov bx,FILE_HANDLE ; Set BX to current File Handle
- mov dx,READ_PTR ; Point DX to read buffer
- mov cx,READ_LENGTH ; Set CX to read buffer length
- mov ah,3fh ; Request read file
- int 21h ; Call PC-DOS
- jnc RD_OK ; No carry, then read was Ok
- lea DX,READ_FAILURE ; Can't imagine what error occurred
- jmp EX_RD ; unless coding error in file handle
- RD_OK: cmp cx,ax ; If CX chars were read (noted in AX)
- je NO_EOF ; then not at end of file (CF clears)
- mov EOF_FOUND,1 ; Otherwise, end of file reached
- NO_EOF: mov cx,ax ; Refresh CX in case end of file reached
- EX_RD: ret ; Return to caller
- READ_FILE endp
- ;
- PRINT proc near ; Format and print output buffer
- mov si,READ_PTR ; Set SI to read buffer
- FORMAT: cmp LINE_COUNT,MAX_LINES ; Is page full?
- jb LOAD ; No, go get next character
- call NEW_PAGE ; Yes, print end of page / new page
- call PAGE_HEAD ; Print page header
- LOAD: lodsb ; Get character to AL
- cmp al,26 ; Check for EOF character
- je AGAIN ; Ignore it
- cmp al,9 ; Is AL a Tab?
- jne PUT_IT ; No, put char in print buffer
- mov al,32 ; Load AL with blank to expand Tab
- TAB_X: stosb ; Move AL to print buffer
- inc CHAR_COUNT ; Increment line character counter
- test CHAR_COUNT,7 ; Is Tab expanded? (this does mod 8)
- jnz TAB_X ; No, keep loading blanks
- jmp WDTH ; Go check current line width
- PUT_IT: stosb ; Move AL to print buffer
- inc CHAR_COUNT ; Increment line character counter
- cmp al,13 ; Is AL a CR?
- je AGAIN ; Yes, go force next character
- cmp al,10 ; Is AL a LF?
- jne FF ; No, check for Form Feed
- call PRINT_LINE ; Yes, print current output buffer
- jmp AGAIN ; Go get next character
- FF: cmp al,12 ; Is AL a Form Feed?
- jne WDTH ; No, check current width
- call NEW_PAGE ; Yes, print end of page / new page
- call PAGE_HEAD ; Print page header
- jmp AGAIN ; Re-start loop
- WDTH: cmp CHAR_COUNT,MAX_CHARS ; Is buffer full?
- jb AGAIN ; No, go get next character
- cmp byte ptr [si],13 ; Yes, see if CR is next character
- je AGAIN ; Yes, then go get it and continue
- mov ah,10 ; No, force CR,LF sequence
- mov al,13 ; into print buffer
- stosw ; Move AX to print buffer
- add CHAR_COUNT,2 ; Add two bytes to character counter
- call PRINT_LINE ; Print the line
- AGAIN: loop FORMAT ; Loop bottom
- ret ; Return to caller
- PRINT endp
- ;
- PRINT_LINE proc near ; Print a full or complete line
- push ax ; Save affected registers
- push cx ; currently in use
- mov dx,PRINT_PTR ; Set DX to point to buffer
- mov cx,CHAR_COUNT ; Print CHAR_COUNT characters
- mov bx,PRN ; PC-DOS printer device
- mov ah,40h ; Request write to device
- int 21h ; Call PC-DOS - error unlikely here
- mov di,PRINT_PTR ; Refresh DI
- mov CHAR_COUNT,0 ; Refresh CHAR_COUNT
- inc LINE_COUNT ; Increment line counter
- pop cx ; Restore registers
- pop ax
- ret ; Return to caller
- PRINT_LINE endp
- ;
- NEW_PAGE proc near ; Print end of page / new page
- cmp al,12 ; Does AL have a form feed?
- je FF_OK ; Yes, so it's in the buffer
- mov al,12 ; No, put one in the buffer
- stosb ; Store AL in the buffer
- inc CHAR_COUNT ; Increment character counter
- FF_OK: call PRINT_LINE ; Print current buffer
- mov LINE_COUNT,0 ; Refresh line counter
- ret ; Return to caller
- NEW_PAGE endp
- ;
- PAGE_HEAD proc near ; Format and print page header
- push di ; Save DI on stack
- inc PAGE_COUNT ; Increase page counter
- mov al,PAGE_COUNT ; Set up to convert page
- lea di,HEAD_3E ; counter to ASCII
- call BIN_2_ASC ; Convert to ASCII
- pop di ; Restore DI
- cmp HEAD_3E[0],'0' ; Does page counter have leading 0?
- jne NOT_0 ; No, don't do anything to it
- mov HEAD_3E[0],' ' ; Yes, make it a blank
- NOT_0: push cx ; Save CX on stack
- mov ah,40h ; Request write to device
- mov bx,PRN ; Request PC-DOS printer device
- lea dx,HEAD_1 ; Point to page header
- mov cx,HEAD_LGTH ; Write all bytes in page header
- int 21h ; Call PC-DOS
- pop cx ; Restore CX
- ret ; Return to caller
- PAGE_HEAD endp
- ;
- STAMP proc near ; Move file name, date & time stamps to page header
- lea si,FN_AREA ; Internal file name
- lea di,HEAD_2B ; Location of file name in page header
- mov cx,70 ; Load up to 70 chars in file name field
- LD_FN1: lodsb ; Get character to AL
- cmp al,0 ; Is it the terminating zero?
- je LD_FN2 ; Yes, go fill remainder with blanks
- stosb ; No, store to page header field
- loop LD_FN1 ; Loop until 0 found or CX zero
- jcxz DATE ; If out of room in page header, quit
- LD_FN2: mov al,32 ; Load rest of field with blanks
- rep stosb
- DATE: mov si,98h ; Date position in default DTA
- lea di,HEAD_3B ; Month position in page header
- lodsw ; Packed word field
- mov bx,ax ; Make a copy in BX
- and ax,01e0h ; Isolate month field
- mov cl,5 ; Align to AL register
- shr ax,cl ; by shifting right 5 bits
- call BIN_2_ASC ; Convert binary month to ASCII
- mov ax,bx ; Restore AX from BX
- and ax,1fh ; Isolate day field
- inc di ; Day position in page header
- call BIN_2_ASC ; Convert binary day to ASCII
- mov ax,bx ; Restore AX from BX
- and ax,0fe00h ; Isolate year field
- shr ah,1 ; Shift right to align
- add ah,80 ; AH is years since 1980
- mov al,ah ; Move to AL for division
- inc di ; Year position in page header
- call BIN_2_ASC ; Convert binary year to ASCII
- TIME: mov si,96h ; Time position in default DTA
- lea di,HEAD_3C ; Hours position in page header
- lodsw ; Packed word field
- mov bx,ax ; Make a copy in BX
- and ax,0f800h ; Isolate hours field
- mov cl,11 ; Align to AL register
- shr ax,cl ; by shifting right 11 bits
- mov HEAD_3D[0],'a' ; Assume it's an 'am' time
- cmp al,12 ; Check for noon
- jb AM_OK ; If less, it's AM
- je PM_OK ; If equal, it's 12 PM
- sub al,12 ; If more, it's after 12 PM
- PM_OK: mov HEAD_3D[0],'p' ; Change 'am' to 'pm'
- AM_OK: call BIN_2_ASC ; Convert binary hours to ASCII
- mov ax,bx ; Restore AX from BX
- and ax,7e0h ; Isolate minutes field
- mov cl,5 ; Align to AL register
- shr ax,cl ; by shifting right 5 bits
- inc di ; Minutes position in page header
- call BIN_2_ASC ; Convert binary minutes to ASCII
- mov ax,bx ; Restore AX from BX
- and ax,1fh ; Isolate seconds field
- inc di ; Seconds position in page header
- call BIN_2_ASC ; Convert binary seconds to ASCII
- ret ; Return to caller
- STAMP endp
- ;
- BIN_2_ASC proc near ; Convert binary number to 2-digit ASCII
- cbw ; Convert AL to word for division
- div BIN_ASC ; Divide AL by BIN_ASC (contains a 10)
- add al,48 ; Convert quotient (in AL) to ASCII
- stosb ; Store to location pointed to by DI
- add ah,48 ; Convert remainder (in AH) to ASCII
- mov al,ah ; Move to AL for store
- stosb ; Store to location pointed to by DI
- ret ; Return to caller
- BIN_2_ASC endp
- ;
- CLOSE_FILE proc near ; Close file handle
- cmp FILE_HANDLE,0 ; If 0, no file open
- je CLOSEX ; Do nothing
- mov bx,FILE_HANDLE ; Move file handle to BX
- mov ah,3eh ; Request close file
- int 21h ; Call PC-DOS
- CLOSEX: ret ; Return to caller
- CLOSE_FILE endp
- CSEG ends
- end BEGIN
-